package com.qianfeng.dbsm.admin.filter;

import com.auth0.jwt.exceptions.TokenExpiredException;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.qianfeng.dbsm.admin.common.MyUserContextHolder;
import com.qianfeng.dbsm.admin.entity.TbMember;
import com.qianfeng.dbsm.admin.service.TbMemberService;
import com.qianfeng.dbsm.admin.util.JWTUtil;
import com.qianfeng.dbsm.admin.util.ResponseUtil;
import com.qianfeng.dbsm.common.ResponseData;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * 功能说明
 *
 * @author 袁俊杰
 * @date 2022-11-12 16:25:24
 */
@Component
public class JWTSecurityFilter extends OncePerRequestFilter {


    @Autowired
    UserDetailsService userService;


    protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {

        String path = httpServletRequest.getRequestURI();
        String token = httpServletRequest.getHeader("Authorization");


        try {
            if (JWTUtil.verify(token)) {
                String username = JWTUtil.getAccount(token);

                //成功了，从token中获取用户的信息
                String account = JWTUtil.getAccount(token);
                //登录成功
                //应该从数据库中查询
                UserDetails userDetails = userService.loadUserByUsername(account);
                // 将用户信息存入 authentication，方便后续校验
                // 创建带权限的token直接会定义成登陆成功
                UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
                authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(httpServletRequest));
                // 将 authentication 存入 ThreadLocal，方便后续获取用户信息
                SecurityContextHolder.getContext().setAuthentication(authentication);
//                return;
            }
        } catch (Exception exception) {
            if (exception instanceof TokenExpiredException) {
                //超时了,1.判断是否存在于tokenmap中，有则表示没有更新过，没有则表示此token已经更新过且已删除
                //2.判断对应的长token是否超时，没有超时即更新长短token，并删除，超时删除tokenmap
                if (JWTUtil.check(token)) {
                    String username = JWTUtil.getAccount(token);
                    //根据短token获得长token
                    String ctoken = JWTUtil.getTokenMap().get(token);
                    //判断长token是否超时
                    try {
                        JWTUtil.verify(ctoken);
                        //删除
                        JWTUtil.delete(token);
                        //更新短token
                        token = JWTUtil.create(username);
                        //更新长token
                        ctoken = JWTUtil.create2(username);
                        //放入tokenmap
                        JWTUtil.put(token, ctoken);
                        //将新的token放入到头部中
                        httpServletResponse.setHeader("token", token);
                        //登录成功
                        UserDetails userDetails = userService.loadUserByUsername(username);
                        // 将用户信息存入 authentication，方便后续校验
                        // 创建带权限的token直接会定义成登陆成功
                        UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
                        authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(httpServletRequest));
                        // 将 authentication 存入 ThreadLocal，方便后续获取用户信息
                        SecurityContextHolder.getContext().setAuthentication(authentication);

                    } catch (Exception exception2) {
                        System.out.println("================进入到了长token失效=====================");
                        exception.printStackTrace();
                    }
                }
            }

        }

        filterChain.doFilter(httpServletRequest,httpServletResponse);
    }
}
